home *** CD-ROM | disk | FTP | other *** search
- /* Machine-dependent code which would otherwise be in inflow.c and core.c,
- for GDB, the GNU debugger.
- Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
-
- This file is part of GDB.
-
- GDB is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 1, or (at your option)
- any later version.
-
- GDB is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GDB; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- #include <stdio.h>
- #include "defs.h"
- #include "param.h"
- #include "frame.h"
- #include "inferior.h"
- #include "symtab.h"
-
- #include <osbind.h>
- #include <mintbind.h>
- #include <unistd.h>
- #include <signal.h>
- #include <ioctl.h>
- #include <process.h>
- #include <ctype.h>
- #include <st-out.h>
- #include <fcntl.h>
- #include <stat.h>
- #include <regexp.h>
- #include <setjmp.h>
- #include <limits.h>
-
- long _stksize = 100 * 1024;
-
- /* Nonzero if we are debugging an attached outside process
- rather than an inferior. */
-
- extern int attach_flag;
-
- extern int errno;
-
- static int inferior_fd;
- long inferior_base_address = 0;
-
- #ifndef PTRACESFLAGS
- #define PTRACESFLAGS (('P'<< 8) | 6)
- #define PTRACEGFLAGS (('P'<< 8) | 7)
- #define P_ENABLE (1 << 0)
- #define PTRACEGO (('P'<< 8) | 8)
- #define PTRACESTEP (('P'<< 8) | 10)
- #endif
-
- int
- call_ptrace (request, pid, procaddr, buf)
- int request, pid, procaddr, buf;
- {
- int fd;
- short flag = P_ENABLE;
-
- if (request != 0)
- error ("no ptrace");
- fd = open ("u:/proc/.-1", O_RDONLY);
- if (fd < 0)
- perror_with_name ("ptrace");
- ioctl (fd, PTRACESFLAGS, &flag);
- close (fd);
- return 0;
- }
-
- #ifdef NO_SHELL
- /* If there is no /bin/sh available, this function executes the program,
- recognizing some simple redirections. */
-
- int
- atari_exec (char *cmd, char **envp)
- {
- char *p;
- char *execname;
- char **argv;
- char *input, *output;
- int append;
- int argc;
- int fd;
- short flag = P_ENABLE;
- long ret;
-
- /* This function should not use any library function which can change
- the parent because of vfork (e.g, the isatty flags with open,
- dup, or dup2) */
- execname = cmd + 5; /* "exec " */
- for (p = execname; *p && !isspace (*p); p++) ;
- argv = alloca ((strlen (p) / 2 + 2) * sizeof (char *));
- argc = 0;
- argv[argc++] = execname;
- input = 0;
- output = 0;
- while (*p)
- {
- *p++ = 0;
- while (isspace (*p))
- p++;
- if (*p == 0)
- break;
- if (*p == '<')
- {
- p++;
- while (isspace (*p))
- p++;
- input = p;
- }
- else if (*p == '>')
- {
- append = *++p == '>';
- if (append)
- p++;
- while (isspace (*p))
- p++;
- output = p;
- }
- else
- argv[argc++] = p;
- while (*p && !isspace (*p))
- p++;
- }
- argv[argc++] = NULL;
- if (input)
- {
- char xinput[PATH_MAX];
- _unx2dos (input, xinput);
- fd = Fopen (xinput, O_RDONLY);
- if (fd >= 0 && fd != 0)
- {
- Fclose (0);
- Fforce (0, fd);
- Fclose (fd);
- }
- }
- if (output)
- {
- char xoutput[PATH_MAX];
- _unx2dos (output, xoutput);
- fd = Fopen (output, O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC));
- if (fd >= 0 && fd != 1)
- {
- Fclose (1);
- Fforce (1, fd);
- Fclose (fd);
- }
- }
- fd = Fopen ("U:\\proc\\.-1", 0);
- if (fd < 0)
- {
- errno = -fd;
- return -1;
- }
- if ((ret = Fcntl (fd, &flag, PTRACESFLAGS)) < 0)
- {
- errno = -ret;
- return -1;
- }
- Fclose (fd);
- return _spawnve (P_OVERLAY, execname, argv, envp);
- }
- #endif
-
- static void relocate_apropriate_symbols ();
-
- void
- relocate_addresses ()
- {
- long base_address, text_base;
-
- ioctl (inferior_fd, PBASEADDR, &base_address);
- lseek (inferior_fd, base_address + 8, 0);
- read (inferior_fd, &text_base, sizeof (long));
- relocate_apropriate_symbols (text_base - inferior_base_address);
- relocate_breakpoints (text_base - inferior_base_address);
- inferior_base_address = text_base;
- }
-
- void
- unrelocate_addresses ()
- {
- relocate_apropriate_symbols (-inferior_base_address);
- relocate_breakpoints (-inferior_base_address);
- inferior_base_address = 0;
- }
-
- void
- create_inferior_hook (pid)
- int pid;
- {
- char procname[16];
-
- sprintf (procname, "u:/proc/.%03d", pid);
- inferior_fd = open (procname, O_EXCL | O_RDWR);
- if (inferior_fd < 0)
- perror_with_name ("open");
- #ifdef NO_SHELL
- relocate_addresses ();
- #endif
- }
-
- kill_inferior ()
- {
- short sig = SIGKILL;
- short zero = 0;
- if (inferior_pid == 0)
- return;
- ioctl (inferior_fd, PTRACEGO, &sig);
- close (inferior_fd);
- inferior_fd = 0;
- wait (0);
- inferior_died ();
- }
-
- /* This is used when GDB is exiting. It gives less chance of error.*/
-
- kill_inferior_fast ()
- {
- short sig = SIGKILL;
- short zero = 0;
- if (inferior_pid == 0)
- return;
- ioctl (inferior_fd, PTRACEGO, &sig);
- close (inferior_fd);
- inferior_fd = 0;
- wait (0);
- }
-
- /* Resume execution of the inferior process.
- If STEP is nonzero, single-step it.
- If SIGNAL is nonzero, give it that signal. */
-
- void
- resume (step, signal)
- int step;
- int signal;
- {
- short sig = signal;
- if (ioctl (inferior_fd, step ? PTRACESTEP : PTRACEGO, &sig) < 0)
- perror_with_name ("resume");
- }
-
- /* Replacement for the wait library routine. GDB assumes that traced
- processes are always reported by wait, but MiNT treats them like
- stopped processes, and reports them only if WUNTRACED is set. */
-
- int
- wait (status)
- int *status;
- {
- long r;
- int exit_status, sig_term, pid;
-
- r = Pwait3 (2, 0L);
-
- if (r < 0)
- {
- errno = (int) -r;
- return -1;
- }
- pid = (int) ((r & 0xffff0000L) >> 16);
- if (status)
- {
- exit_status = r & 0x000000ffL;
- sig_term = (r & 0x00007f00L) >> 8;
- if (sig_term >= NSIG)
- sig_term = 0;
- if (sig_term && exit_status != 0 && exit_status != 0177)
- sig_term = 0;
- if (exit_status == 0177 && sig_term)
- *status = (sig_term << 8) | 0177;
- else
- *status = (exit_status << 8) | sig_term;
- }
- return pid;
- }
-
- #ifdef ATTACH_DETACH
-
- /* Start debugging the process whose number is PID. */
-
- attach (pid)
- int pid;
- {
- char procname[16];
- int fd;
- short flag = P_ENABLE;
- sprintf (procname, "u:/proc/.%03d", pid);
- fd = open (procname, O_EXCL | O_RDWR);
- if (fd < 0)
- perror_with_name ("attach");
- if (ioctl (fd, PTRACESFLAGS, &flag) < 0)
- {
- close (fd);
- perror_with_name ("PTRACESFLAGS");
- }
- kill (pid, SIGTRAP);
- attach_flag = 1;
- setpgid (pid, pid);
- inferior_fd = fd;
- relocate_addresses ();
- return pid;
- }
-
- /* Stop debugging the process whose number is PID
- and continue it with signal number SIGNAL.
- SIGNAL = 0 means just continue it. */
-
- void
- detach (signal)
- int signal;
- {
- short sig = signal;
- short zero = 0;
- ioctl (inferior_fd, PTRACEGO, &sig);
- ioctl (inferior_fd, PTRACESFLAGS, &zero);
- close (inferior_fd);
- inferior_fd = 0;
- attach_flag = 0;
- unrelocate_addresses ();
- }
- #endif /* ATTACH_DETACH */
-
- struct context
- {
- long regs[15]; /* registers d0-d7, a0-a6 */
- long usp; /* user stack pointer (a7) */
- short sr; /* status register */
- long pc; /* program counter */
- long ssp; /* supervisor stack pointer */
- long term_vec; /* GEMDOS terminate vector (0x102) */
- char fstate[216]; /* FPU internal state */
- long fregs[3*8]; /* registers fp0-fp7 */
- long fctrl[3]; /* FPCR/FPSR/FPIAR */
- };
-
- void
- fetch_inferior_registers ()
- {
- long place, ctxtsize;
- struct context inferior_context;
- extern char registers[];
-
- ioctl (inferior_fd, PPROCADDR, &place);
- /* Position on the first context. */
- ioctl (inferior_fd, PCTXTSIZE, &ctxtsize);
- lseek (inferior_fd, place - 2 * ctxtsize, 0);
- read (inferior_fd, &inferior_context, sizeof (struct context));
-
- bcopy (inferior_context.regs, registers, 16 * 4);
- #ifdef FP0_REGNUM
- bcopy (inferior_context.fregs, ®isters[REGISTER_BYTE (FP0_REGNUM)],
- sizeof inferior_context.fregs);
- #endif
- *(long *) ®isters[REGISTER_BYTE (PS_REGNUM)] = inferior_context.sr;
- *(long *) ®isters[REGISTER_BYTE (PC_REGNUM)] = inferior_context.pc;
- #ifdef FP0_REGNUM
- bcopy (inferior_context.fctrl, ®isters[REGISTER_BYTE (FPC_REGNUM)],
- sizeof inferior_context.fctrl);
- #endif
- }
-
- /* Store our register values back into the inferior.
- If REGNO is -1, do this for all registers.
- Otherwise, REGNO specifies which register (so we can save time). */
-
- store_inferior_registers (regno)
- int regno;
- {
- long place, ctxtsize;
- struct context inferior_context;
- extern char registers[];
-
- ioctl (inferior_fd, PPROCADDR, &place);
- /* Position on the first context. */
- ioctl (inferior_fd, PCTXTSIZE, &ctxtsize);
- place -= 2 * ctxtsize;
- lseek (inferior_fd, place, 0);
- read (inferior_fd, &inferior_context, sizeof (struct context));
-
- bcopy (registers, inferior_context.regs, 16 * 4);
- #ifdef FP0_REGNUM
- bcopy (®isters[REGISTER_BYTE (FP0_REGNUM)], inferior_context.fregs,
- sizeof inferior_context.fregs);
- #endif
- inferior_context.sr &= ~0xff;
- inferior_context.sr |= *(long *) ®isters[REGISTER_BYTE (PS_REGNUM)] & 0xff;
- inferior_context.pc = *(long *) ®isters[REGISTER_BYTE (PC_REGNUM)];
-
- #ifdef FP0_REGNUM
- bcopy (®isters[REGISTER_BYTE (FPC_REGNUM)],
- inferior_context.fctrl, sizeof inferior_context.fctrl);
- #endif
- lseek (inferior_fd, place, 0);
- write (inferior_fd, &inferior_context, sizeof (struct context));
- }
-
- /* the MiNT proc file system doesn't catch bus errors (yet), we must do it
- ourselves */
-
- jmp_buf bus_error;
-
- void
- sigbus (signo)
- int signo;
- {
- errno = EACCESS;
- longjmp (bus_error, 1);
- }
-
- /* Copy LEN bytes from inferior's memory starting at MEMADDR
- to debugger memory starting at MYADDR.
- On failure (cannot read from inferior, usually because address is out
- of bounds) returns the value of errno. */
-
- int
- read_inferior_memory (memaddr, myaddr, len)
- CORE_ADDR memaddr;
- char *myaddr;
- int len;
- {
- void (*old_sigbus) ();
-
- errno = 0;
- lseek (inferior_fd, memaddr, 0);
- old_sigbus = signal (SIGBUS, sigbus);
- if (setjmp (bus_error) == 0)
- read (inferior_fd, myaddr, len);
- signal (SIGBUS, old_sigbus);
- if (errno)
- bzero (myaddr, len);
- return errno;
- }
-
- /* Copy LEN bytes of data from debugger memory at MYADDR
- to inferior's memory at MEMADDR.
- On failure (cannot write the inferior)
- returns the value of errno. */
-
- /* WARNING: MiNT writes in supervisor mode, no access restrictions
- (except nonexistent memory, of course) */
- /* News Flash: Now since MiNT has memory protection, the situation
- is far better. */
-
- int
- write_inferior_memory (memaddr, myaddr, len)
- CORE_ADDR memaddr;
- char *myaddr;
- int len;
- {
- void (*old_sigbus) ();
-
- errno = 0;
- lseek (inferior_fd, memaddr, 0);
- old_sigbus = signal (SIGBUS, sigbus);
- if (setjmp (bus_error) == 0)
- write (inferior_fd, myaddr, len);
- signal (SIGBUS, old_sigbus);
- return errno;
- }
-
-
- /* Machine-dependent code which would otherwise be in core.c */
- /* Work with core dump and executable files, for GDB. */
-
- #define AOUTHDR struct aexec
-
- extern char *sys_siglist[];
-
- /* Hook for `exec_file_command' command to call. */
-
- extern void (*exec_file_display_hook) ();
-
- /* File names of core file and executable file. */
-
- extern char *corefile;
- extern char *execfile;
-
- /* Descriptors on which core file and executable file are open.
- Note that the execchan is closed when an inferior is created
- and reopened if the inferior dies or is killed. */
-
- extern int corechan;
- extern int execchan;
-
- /* Last modification time of executable file.
- Also used in source.c to compare against mtime of a source file. */
-
- extern int exec_mtime;
-
- /* Virtual addresses of bounds of the two areas of memory in the core file. */
-
- extern CORE_ADDR data_start;
- extern CORE_ADDR data_end;
- extern CORE_ADDR stack_start;
- extern CORE_ADDR stack_end;
-
- /* Virtual addresses of bounds of two areas of memory in the exec file.
- Note that the data area in the exec file is used only when there is no core file. */
-
- extern CORE_ADDR text_start;
- extern CORE_ADDR text_end;
-
- extern CORE_ADDR exec_data_start;
- extern CORE_ADDR exec_data_end;
-
- /* Address in executable file of start of text area data. */
-
- extern int text_offset;
-
- /* Address in executable file of start of data area data. */
-
- extern int exec_data_offset;
-
- /* Address in core file of start of data area data. */
-
- extern int data_offset;
-
- /* Address in core file of start of stack area data. */
-
- extern int stack_offset;
-
- /* a.out header saved in core file. */
-
- extern AOUTHDR core_aouthdr;
-
- /* a.out header of exec file. */
-
- extern AOUTHDR exec_aouthdr;
-
- extern void validate_files ();
-
- core_file_command (filename, from_tty)
- char *filename;
- int from_tty;
- {
- error ("No core files yet");
- }
-
- exec_file_command (filename, from_tty)
- char *filename;
- int from_tty;
- {
- int val;
-
- /* Eliminate all traces of old exec file.
- Mark text segment as empty. */
-
- if (execfile)
- free (execfile);
- execfile = 0;
- data_start = 0;
- data_end -= exec_data_start;
- text_start = 0;
- text_end = 0;
- exec_data_start = 0;
- exec_data_end = 0;
- if (execchan >= 0)
- close (execchan);
- execchan = -1;
-
- /* Now open and digest the file the user requested, if any. */
-
- if (filename)
- {
- filename = tilde_expand (filename);
- make_cleanup (free, filename);
-
- execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0,
- &execfile);
- if (execchan < 0)
- perror_with_name (filename);
-
- {
- struct stat st_exec;
- val = myread (execchan, &exec_aouthdr, sizeof (AOUTHDR));
-
- if (val < 0)
- perror_with_name (filename);
-
- text_start = 0;
- exec_data_start = exec_aouthdr.a_text;
- text_offset = A_TXTOFF (exec_aouthdr);
- exec_data_offset = A_TXTOFF (exec_aouthdr) + exec_aouthdr.a_text;
-
- text_end = text_start + exec_aouthdr.a_text;
- exec_data_end = exec_data_start + exec_aouthdr.a_data;
- data_start = exec_data_start;
- data_end += exec_data_start;
-
- fstat (execchan, &st_exec);
- exec_mtime = st_exec.st_mtime;
- }
-
- validate_files ();
- }
- else if (from_tty)
- printf ("No exec file now.\n");
-
- /* Tell display code (if any) about the changed file name. */
- if (exec_file_display_hook)
- (*exec_file_display_hook) (filename);
- }
-
- /* Check for a real FPU by looking at the _FPU cookie. */
-
- static int
- get_fpu_cookie ()
- {
- long *cookie = *(long **) 0x5a0L;
-
- if (cookie == 0L)
- return 0L;
- for (; *cookie; cookie += 2)
- if (*cookie == 0x5f465055) /* _FPU */
- return cookie[1];
- return 0L;
- }
-
- int
- check_fpu ()
- {
- long fpu = Supexec (get_fpu_cookie);
-
- /* Return true if there is a real fpu or a line F emulator. */
- return ((fpu >> 16) > 1 || fpu & 0xffff);
- }
-
- /* walk through the symbol table and relocate apropriate */
- /* from the gdb-2.6 port, modified to support partial symtabs */
-
- static void
- relocate_apropriate_block_symbols (block, offset)
- struct block *block;
- long offset;
- {
- struct symbol *sym;
- int nsyms, symnum;
-
- BLOCK_START (block) += offset;
- BLOCK_END (block) += offset;
- nsyms = BLOCK_NSYMS (block);
- for (symnum = 0; symnum < nsyms; symnum++)
- {
- sym = BLOCK_SYM (block, symnum);
- if (sym->namespace == VAR_NAMESPACE
- && (sym->class == LOC_STATIC || sym->class == LOC_LABEL))
- sym->value.value += offset;
- }
- }
-
- static void
- relocate_apropriate_symbols (offset)
- long offset;
- {
- struct symtab *s;
- struct partial_symtab *ps;
- struct symbol *sym;
- struct blockvector *bv, *last_bv = 0;
- struct block *block;
- struct linetable *l;
- int nsyms, symnum, i;
-
- for (s = symtab_list; s; s = s->next)
- {
- l = LINETABLE (s);
- for (i = 0; i < l->nitems; i++)
- l->item[i].pc += offset;
- bv = BLOCKVECTOR (s);
- if (bv == last_bv)
- /* already relocated */
- continue;
- last_bv = bv;
- for (i = 0; i < BLOCKVECTOR_NBLOCKS (bv); i++)
- {
- block = BLOCKVECTOR_BLOCK (bv, i);
- relocate_apropriate_block_symbols (block, offset);
- }
- }
- for (ps = partial_symtab_list; ps; ps = ps->next)
- {
- ps->textlow += offset;
- ps->texthigh += offset;
- }
- /* relocate the misc functions */
- for (i = 0; i < misc_function_count; i++)
- misc_function_vector[i].address += offset;
- }
-
- #ifndef __REGEX_LIBRARY_H__
- static char *regcomp_error = 0;
- static regexp *compiled_regex = 0;
-
- /* Remember the last error message from regcomp */
- void
- regerror(message)
- char *message;
- {
- regcomp_error = message;
- }
-
- char *
- re_comp (regex)
- char *regex;
- {
- regcomp_error = NULL;
- if (compiled_regex)
- free (compiled_regex);
- if (compiled_regex = regcomp (regex))
- return NULL;
- else
- return regcomp_error;
- }
-
- int
- re_exec (buffer)
- char *buffer;
- {
- if (compiled_regex)
- return regexec (compiled_regex, buffer, 1);
- else
- return -1;
- }
- #endif /* __REGEX_LIBRARY_H__ */
-